home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000…tember: Reference Library / Dev.CD Sep 00 RL Disk 1.toast / mac / Technical Documentation / Develop / Additional Articles / Developing Symbiotic Apps / Symbiotic Samples / UAppleEvents.cp Folder / UAppleEvents.cp < prev    next >
Encoding:
Text File  |  1996-10-28  |  8.1 KB  |  348 lines  |  [TEXT/CWIE]

  1. // UAppleEvents © 1996 Nick Beadman
  2. //    Utility class for helping handle the AppleEvent Manager
  3.  
  4. #include <UAEGizmos.h>
  5.  
  6. #include "UAppleEvents.h"
  7.  
  8. AEIdleProcPtr UAppleEvents::sIdleFunc = DefaultAEIdleFunc;
  9. Boolean UAppleEvents::sRecording = false;
  10.  
  11. #pragma mark ==== Object Specification ====
  12.  
  13. OSErr UAppleEvents::GetContainer(const AEDesc& inObjectSpecifier, AEDesc& outContainer)
  14. {
  15.     OSErr lErr = noErr;
  16.     
  17.     try
  18.     {
  19.         LAESubDesc lSubDesc(inObjectSpecifier);
  20.         lSubDesc = lSubDesc.KeyedItem(keyAEContainer);
  21.         lSubDesc.ToDesc(&outContainer);
  22.     }
  23.     catch(ExceptionCode inErr)
  24.     {
  25.         lErr = inErr;
  26.     }
  27.     
  28.     return lErr;
  29. }
  30.  
  31. #pragma mark ==== Sending ====
  32.  
  33. OSErr UAppleEvents::SendWaitReply(const AppleEvent& inEvent, AppleEvent& outReply, Int32 inTimeout, AESendMode inAdditionalAttr)
  34. {
  35.     AEIdleUPP lIdleFunc;
  36.     OSErr lErr;
  37.  
  38.     if (sIdleFunc != nil)
  39.     {
  40.         lIdleFunc = NewAEIdleProc(sIdleFunc);
  41.     }
  42.     else
  43.     {
  44.         lIdleFunc = nil;
  45.     }
  46.     
  47.     lErr = ::AESend(&inEvent, &outReply, kAEWaitReply | inAdditionalAttr, kAENormalPriority, inTimeout, lIdleFunc, nil);
  48.     
  49.     if (lIdleFunc != nil)
  50.     {
  51.         DisposeRoutineDescriptor(lIdleFunc);
  52.     }
  53.  
  54.     ExtractOSErr(outReply, lErr);
  55.     
  56.     return lErr;
  57. }
  58.  
  59. OSErr UAppleEvents::SendNoReply(const AppleEvent& inEvent, AESendMode inAdditionalAttr)
  60. {
  61.     OSErr lErr;
  62.     StAEDescriptor lReply;
  63.     
  64.     lErr = ::AESend(&inEvent, lReply, kAENoReply | inAdditionalAttr, kAENormalPriority, kAEDefaultTimeout, nil, nil);
  65.     
  66.     return lErr;
  67. }
  68.  
  69. #pragma mark ==== Reply Checking ====
  70.  
  71. Boolean UAppleEvents::ExtractOSErr(const AppleEvent& inReply, OSErr& outErr)
  72. {
  73.     LAESubDesc lSubDesc(inReply);
  74.     
  75.     // check for an error number
  76.     LAESubDesc lErrorNumber(lSubDesc.KeyedItem(keyErrorNumber));
  77.     if (lErrorNumber.GetType() != typeNull)
  78.     {
  79.         // attempt to get it as an OSErr
  80.         outErr = lErrorNumber.ToInt16();
  81.         return true;
  82.     }
  83.     
  84.     return false;
  85. }
  86.  
  87. Boolean UAppleEvents::ExtractErrorString(const AppleEvent& inReply, StringPtr outString)
  88. {
  89.     LAESubDesc lSubDesc(inReply);
  90.     
  91.     // look for an error string
  92.     LAESubDesc lErrorString(lSubDesc.KeyedItem(keyErrorString));
  93.     if (lErrorString.GetType() != typeNull)
  94.     {
  95.         // attempt to get it as a pascal string
  96.         lErrorString.ToPString(outString);
  97.         return true;
  98.     }
  99.     
  100.     return false;
  101. }
  102.  
  103. #pragma mark ==== User Interaction ====
  104.  
  105. OSErr UAppleEvents::InteractWithUser(NMRecPtr inNotificationRequest, Int32 inTimeout)
  106. {
  107.     AEIdleUPP lIdleFunc;
  108.     OSErr lErr;
  109.  
  110.     if (sIdleFunc != nil)
  111.     {
  112.         lIdleFunc = NewAEIdleProc(sIdleFunc);
  113.     }
  114.     else
  115.     {
  116.         lIdleFunc = nil;
  117.     }
  118.     
  119.     lErr = ::AEInteractWithUser(inTimeout, inNotificationRequest, lIdleFunc);
  120.     
  121.     if (lIdleFunc != nil)
  122.     {
  123.         DisposeRoutineDescriptor(lIdleFunc);
  124.     }
  125.  
  126.     return lErr;
  127. }
  128.  
  129. #pragma mark ==== Recording ====
  130.  
  131. OSErr UAppleEvents::InitRecordability(void)
  132. {
  133.     // install a start and stop recording handler
  134.     OSErr lErr;
  135.     
  136.     lErr = ::AEInstallEventHandler(kCoreEventClass, kAENotifyStartRecording,
  137.                         NewAEEventHandlerProc(UAppleEvents::RecordingHandler),
  138.                         true, false);
  139.     if (lErr != noErr)
  140.     {
  141.         return lErr;
  142.     }
  143.     
  144.     lErr = ::AEInstallEventHandler(kCoreEventClass, kAENotifyStopRecording,
  145.                         NewAEEventHandlerProc(UAppleEvents::RecordingHandler),
  146.                         false, false);
  147.  
  148.     return lErr;                        
  149. }
  150.  
  151. OSErr UAppleEvents::Record(const AppleEvent& inAppleEvent)
  152. {
  153.     if (!sRecording)
  154.     {
  155.         return errAEUnknownSendMode;
  156.     }
  157.  
  158.     OSErr lErr = noErr;
  159.     
  160.     try
  161.     {
  162.         // make a self addressed target
  163.         StAEDescriptor lOurselves;
  164.         ThrowIfOSErr_(UAppleEvents::MakeSelfAddressDesc(lOurselves));
  165.         
  166.         // duplicate the event and change address
  167.         StAEDescriptor lRecordAppleEvent;
  168.         ThrowIfOSErr_(::AEDuplicateDesc(&inAppleEvent, lRecordAppleEvent));
  169.         ThrowIfOSErr_(::AEPutAttributeDesc(lRecordAppleEvent, keyAddressAttr, lOurselves));
  170.  
  171.         // send the apple event, without a reply and no executing
  172.         ThrowIfOSErr_(UAppleEvents::SendNoReply(lRecordAppleEvent, kAEDontExecute));
  173.     }
  174.     catch(ExceptionCode inErr)
  175.     {
  176.         lErr = inErr;
  177.     }
  178.     
  179.     return lErr;
  180. }
  181.  
  182. pascal OSErr UAppleEvents::RecordingHandler(const AppleEvent*, AppleEvent*, Int32 inRefCon)
  183. {
  184.     sRecording = (inRefCon == true);
  185.     
  186.     return noErr;
  187. }
  188.  
  189. #pragma mark ==== Self Addressing ====
  190.  
  191. OSErr UAppleEvents::MakeSelfAddressDesc(AEAddressDesc& outSelfAddressDesc)
  192. {
  193.     ProcessSerialNumber lCurrentProcess;
  194.     
  195.     lCurrentProcess.highLongOfPSN = 0;
  196.     lCurrentProcess.lowLongOfPSN = kCurrentProcess;
  197.     
  198.     return ::AECreateDesc(typeProcessSerialNumber, (Ptr)&lCurrentProcess, 
  199.                         sizeof(ProcessSerialNumber), &outSelfAddressDesc);
  200. }
  201.  
  202. #pragma mark ==== Comparison ====
  203.  
  204. Boolean UAppleEvents::EqualTargetIDs(const TargetID& inTargetIDOne, const TargetID& inTargetIDTwo)
  205. {
  206.     // assume they are different unless all of this is true
  207.     // field by field compare (of name and location)
  208.     if (inTargetIDOne.location.locationKindSelector != inTargetIDTwo.location.locationKindSelector)
  209.     {
  210.         return false;
  211.     }
  212.     // now if it the locationKindSelector is ppcNBPLocation then look at NBPEntry
  213.     if (inTargetIDOne.location.locationKindSelector == ppcNBPLocation)
  214.     {
  215.         // the NBPEntity doesn't appear to be packed
  216.         if (!::EqualString(inTargetIDOne.location.u.nbpEntity.objStr,
  217.                 inTargetIDTwo.location.u.nbpEntity.objStr, false, false))
  218.         {
  219.             return false;
  220.         }
  221.         if (!::EqualString(inTargetIDOne.location.u.nbpEntity.zoneStr,
  222.                 inTargetIDTwo.location.u.nbpEntity.zoneStr, false, false))
  223.         {
  224.             return false;
  225.         }
  226.         if (!::EqualString(inTargetIDOne.location.u.nbpEntity.typeStr,
  227.                 inTargetIDTwo.location.u.nbpEntity.typeStr, false, false))
  228.         {
  229.             return false;
  230.         }
  231.         
  232.     }
  233.     if (!::EqualString(inTargetIDOne.name.name, inTargetIDTwo.name.name, false, false))
  234.     {
  235.         return false;
  236.     }
  237.     
  238.     return true;
  239. }
  240.  
  241. // object specifiers need to be of the same class (byID, byName, ...) for this to work
  242.  
  243. Boolean UAppleEvents::EqualObjectSpecifiers(const AEDesc& inObjectSpecOne, const AEDesc& inObjectSpecTwo)
  244. {
  245.     // special case the null object
  246.     if (inObjectSpecOne.descriptorType == typeNull || inObjectSpecTwo.descriptorType == typeNull)
  247.     {
  248.         return inObjectSpecOne.descriptorType == inObjectSpecTwo.descriptorType;
  249.     }
  250.     
  251.     LAESubDesc lObjectSpecOne(inObjectSpecOne);
  252.     LAESubDesc lObjectSpecTwo(inObjectSpecTwo);
  253.     
  254.     // compare the object classes (keyAEDesiredClass)
  255.     DescType lObjectClass;
  256.     {
  257.         LAESubDesc lClass = lObjectSpecOne.KeyedItem(keyAEDesiredClass);
  258.         lObjectClass = lClass.ToType();
  259.     }
  260.     DescType lInObjectClass;
  261.     {
  262.         LAESubDesc lClass = lObjectSpecTwo.KeyedItem(keyAEDesiredClass);
  263.         lInObjectClass = lClass.ToType();
  264.     }
  265.     if (lInObjectClass != lObjectClass)
  266.     {
  267.         return false;
  268.     }
  269.     
  270.     // compare the selection data
  271.     StAEDescriptor lData;
  272.     {
  273.         LAESubDesc lKeyData = lObjectSpecOne.KeyedItem(keyAEKeyData);
  274.         lKeyData.ToDesc(&lData.mDesc);
  275.     }
  276.     StAEDescriptor inData;
  277.     {
  278.         LAESubDesc lKeyData = lObjectSpecTwo.KeyedItem(keyAEKeyData);
  279.         lKeyData.ToDesc(&inData.mDesc);
  280.     }
  281.     if (!(UAppleEventsMgr::CompareDescriptors(lData.mDesc, kAEEquals, inData.mDesc)))
  282.     {
  283.         return false;
  284.     }
  285.     
  286.     return true;
  287. }
  288.  
  289. #pragma mark ==== Idling ====
  290.  
  291. void UAppleEvents::SetIdleFunc(AEIdleProcPtr inIdleFunc)
  292. {
  293.     // Set the idle func. Nil is now NOT ALLOWED - if you specifiy kAEWaitReply, you MUST
  294.     // provide an idle func. To prevent idle processing, set the idle func to NullAEIdleFunc.
  295.  
  296.     ThrowIfNil_(inIdleFunc);
  297.     
  298.     sIdleFunc = inIdleFunc;
  299. }
  300.  
  301. pascal Boolean UAppleEvents::DefaultAEIdleFunc(EventRecord* inEvent, long* ioSleepTime, RgnHandle*)
  302. {
  303.     Boolean lUserCancelled = false;
  304.     
  305.     // first check for command-period in all keyDown events
  306.     EventRecord lKeyEvent;
  307.     while (::GetOSEvent(keyDownMask, &lKeyEvent))
  308.     {
  309.         if (UKeyFilters::IsCmdPeriod(lKeyEvent))
  310.         {
  311.             lUserCancelled = true;
  312.             break;
  313.         }
  314.     }
  315.     
  316.     // now process the event, similar to LApplication::ProcessNextEvent
  317.     //     only update,activate, os and null events are documented to come thru here
  318.     //    Note: it cannot get at the sleep time, mouse moved region or attachments
  319.     switch(inEvent->what)
  320.     {
  321.         case updateEvt:
  322.         case osEvt:
  323.         case activateEvt:
  324.         {
  325.             LEventDispatcher::GetCurrentEventDispatcher()->DispatchEvent(*inEvent);
  326.         }
  327.         break;
  328.         
  329.         case nullEvent:
  330.         {
  331.             LEventDispatcher::GetCurrentEventDispatcher()->UseIdleTime(*inEvent);
  332.             // set the sleep time
  333.             *ioSleepTime = 12;
  334.         }
  335.         break;
  336.     }
  337.     // periodicals get time after every event
  338.     LPeriodical::DevoteTimeToRepeaters(*inEvent);
  339.  
  340.     return lUserCancelled;
  341. }
  342.  
  343. pascal Boolean UAppleEvents::NullAEIdleFunc(EventRecord*, long*, RgnHandle*)
  344. {
  345.     return false;
  346. }
  347.  
  348.